<script setup lang="ts">
import { reactive, computed, onMounted, watch, ref } from 'vue'
import { useForm } from '@/composeAPI/useForm'
import { useTable } from '@/composeAPI/useTable'
import $element from '@/utils/element'
import type { FormInstance, FormRules } from 'element-plus'

import time from '@/utils/time'
import _ from 'lodash'

const props = defineProps({
  tableType: {
    type: Boolean,
    default: () => true
  },
  rowType: {
    type: Boolean,
    default: () => false
  },
  title: {
    type: String,
    default: ''
  },
  showAddBtn: {
    type: Boolean,
    default: () => true
  },
  showSaveBtn: {
    type: Boolean,
    default: () => true
  },
  rules: {
    type: Object,
    default: () => { }
  },
  loading: {
    type: Boolean,
    default: () => false
  },
  height: {
    type: [String, Number],
    default: () => '100%'
  },
  border: {
    type: Boolean,
    default: () => true
  },
  highLight: {
    type: Boolean,
    default: () => false
  },
  list: {
    type: Array,
    default: () => [] as Array<object>
  },
  listlength: {
    type: Number,
    default: () => null
  },
  showHeader: {
    type: Boolean,
    default: () => true
  },
  columns: {
    type: Array,
    default: () => [] as Array<object>
  }
})

const emit = defineEmits(['command'])

const {
  state: stateForm,
  ruleForm,
  initData,
  getValue,
  validate,
  validateRow
} = useForm()
const { state: stateTable, addRow, addRowType } = useTable()

const state = reactive({
  columns: _.cloneDeepWith(props.columns) as any
})

const isShowHeader = computed(() => {
  return props.title !== '' || props.showAddBtn
})

const init = () => {
  stateTable.tableData = _.cloneDeepWith(props.list)
  initData(state.columns)

  addRowType(!props.showSaveBtn)
}

const add = () => {
  if (!props.listlength) {
    addRow(stateForm.currentData)
  } else {
    if (props.listlength > stateTable.tableData.length) {
      addRow(stateForm.currentData)
    } else {
      $element.toast(`最多添加${props.listlength}条数据`, 'error', 3000)
    }
  }
}

const handleAction = async (command: any, scope: any) => {
  switch (command) {
    case 'edit':
      scope.row.edit = true
      break
    case 'saveRow':
      const res: any = await saveRow(scope.$index)
      if (res) {
        scope.row.edit = false
        emit('command', command, {
          row: scope.row,
          index: scope.$index
        })
      }
      break
    case 'delete':
      const num = stateTable.tableData.indexOf(scope.row)
      // console.log(num)
      if (num > -1) {
        stateTable.tableData.splice(num, 1)
        emit('command', command, {
          row: scope.row,
          index: scope.$index
        })
      }
      break
    default:
      break
  }
}

const save = async () => {
  const res = await validate()
  console.log(res)
  if (res) {
    emit('command', 'saveAll', {
      row: stateTable.tableData,
      index: -1
    })
  }
}

const saveRow = async (index: number) => {
  const key = []
  let errorMessage: any = false
  for (const i in props.rules) {
    key.push(i)
  }

  if (key.length === 0) return

  const colIndex = []

  for (const item of key) {
    const str = 'tableData.' + index + '.' + item
    colIndex.push(str)
  }

  errorMessage = await validateRow(colIndex)

  return errorMessage
}

const setShow = (row: any, link: any) => {
  if (link.show) {
    return link.show(row)
  }

  return true
}

const setDisabled = (row: any, link: any) => {
  if (link.disabled) {
    return link.disabled(row)
  }

  return false
}

watch(() => props.list, (val: any) => {
  stateTable.tableData = val
})

onMounted(() => {
  init()
})

defineExpose({
  stateTable,
  validateRow
})
</script>

<template>
  <div class="flex flex-col items-start justify-start w-full">
    <el-descriptions class="w-full mb-2" v-if="isShowHeader">
      <template #title v-if="props.title !== ''">
        {{ props.title }}
      </template>
      <template #extra>
        <el-button type="primary" @click="add" v-if="props.showAddBtn">新增</el-button>
        <el-button type="primary" @click="save" v-if="props.showSaveBtn">保存</el-button>
      </template>
    </el-descriptions>

    <el-form class="w-full" ref="ruleForm" :model="stateTable" :rules="props.rules">
      <el-table stripe class="w-full" table-layout="fixed" v-loading="props.loading" :border="props.border"
        :height="props.height" :data="stateTable.tableData" :show-header="props.showHeader"
        :highlight-current-row="props.highLight">
        <template v-for="(col, index) in state.columns">
          <el-table-column v-if="col.type === 'index' ||
            col.type === 'selection' ||
            col.type === 'expand'
            " :key="index" :sortable="col.sortable" :prop="col.prop" :align="col.align" :label="col.label"
            :type="col.type" :width="col.width" />
          <el-table-column v-else :key="index + 1" :sortable="col.sortable" :prop="col.prop" :align="col.align"
            :label="col.label" :width="col.width">
            <template #default="{ row, $index }">
              <el-form-item :prop="'tableData.' + $index + '.' + col.prop" :rules="rules[col.prop]">
                <template v-if="col.type === 'date'">
                  <template v-if="row.edit">
                    <date-picker v-model="row[col.prop]" :label="col.label" :type="col.pickerType"
                      :format="col.dateFormat" :disabled="col.editDisabled" />
                  </template>
                  <template v-else>
                    {{
                      row[col.prop] === ''
                      ? time.getCurrentDate(new Date(), col.dateFormat)
                      : time.getCurrentDate(row[col.prop], col.dateFormat)
                    }}
                  </template>
                </template>

                <template v-if="col.type === 'time'">
                  <el-time-picker
                    v-model="row[col.prop]"
                    :teleported="col.teleported"
                    :disabled="col.editDisabled"
                    :format="col.dateFormat"
                    />
                </template>

                <template v-else-if="col.type === 'text'">
                  <template v-if="row.edit">
                    <input-text v-model="row[col.prop]" :disabled="col.editDisabled" :placeholder="'请输入' + col.label" />
                  </template>
                  <template v-else>
                    {{ row[col.prop] }}
                  </template>
                </template>

                <template v-else-if="col.type === 'number'">
                  <template v-if="row.edit">
                    <input-text v-model.number="row[col.prop]" :disabled="col.editDisabled"
                      :placeholder="'请输入' + col.label" />
                  </template>
                  <template v-else>
                    {{ row[col.prop] }}
                  </template>
                </template>

                <template v-else-if="col.type === 'select'">
                  <f-select v-model="row[col.prop]" :list="col.list || row.list" :label="col.label"
                    :clearable="col.clearable" :multiple="col.multiple" :option="col.option"
                    :disabled="col.editDisabled" :teleported="col.teleported" />
                </template>

                <template v-else-if="col.type === 'switch'">
                  <f-switch v-model="row[col.prop]" :activeColor="col.activeColor" :inactiveColor="col.inactiveColor"
                    :active-value="col.activeValue" :inactive-value="col.inactiveValue" :active-text="col.activeText"
                    :inactive-text="col.inactiveText" :disabled="col.editDisabled" />
                </template>

                <template v-else-if="col.buttons?.length">
                  <template v-for="(btn, index) in col.buttons">
                    <el-button :key="index + 100" size="small" :type="btn.type" :disabled="setDisabled(row, btn)"
                      v-if="setShow(row, btn)" @click="handleAction(btn.command, { row, $index })">
                      {{ btn.name }}
                    </el-button>
                  </template>
                </template>
              </el-form-item>
            </template>
          </el-table-column>
        </template>
      </el-table>
    </el-form>
  </div>
</template>

<style lang="scss" scoped>
:deep(.el-descriptions__header) {
  @apply mb-0;
}
</style>
